package pro.shuangxi.web;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapBuilder;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author mengshx
 * @description <p>浏览器</p>
 * @date 2022-08-25 15:16
 **/
@Component
public class WebBrowserUtils {


    static ResourceLoader resourceLoader;
    static Environment environment;
    static ChromeDriver chromeDriver;

    public static void main(String[] args) {
        Object o = new Object();
        Object clone = org.apache.commons.lang3.ObjectUtils.clone(o);
    }
    @Autowired
    public void setParam(ResourceLoader resourceLoader, Environment environment) {

        WebBrowserUtils.resourceLoader = resourceLoader;
        WebBrowserUtils.environment = environment;
    }
    public static void init(){
        try {
            WebDriverManager.chromedriver().setup();
        } catch (Exception e) {
            System.out.println("网络问题，无法下载驱动，请手动下载chromedirver然后配置webdriver.chrome.driver");
            initLocal();
        }
    }
    public static void initLocal(){
        String driverPath = environment.getProperty("webdriver");
            System.setProperty("webdriver.chrome.driver", driverPath);
            System.out.println("本地驱动设置完毕："+driverPath);
    }
    /**
     * 获取web驱动
     * 预执行的script
     *
     * @return 浏览器驱动
     */
    public static ChromeDriver getWebDriver(String preScript) {

        // 设置浏览器参数
        ChromeOptions options = new ChromeOptions();
        options.setScriptTimeout(Duration.ofSeconds(30L));
        options.setPageLoadTimeout(Duration.ofSeconds(100L));
        options.setImplicitWaitTimeout(Duration.ofSeconds(120L));
        Map<String, Object> prefs = new HashMap<String, Object>();
        prefs.put("credentials_enable_service", false);
        prefs.put("profile.password_manager_enabled", false);

        /**
         excludeSwitches", Arrays.asList("enable-automation")在高版本的谷歌浏览器是无法屏蔽
         window.navigator.webdriver 为false 的特征，这里写出来是为了配合其他参数来关闭浏览器上显示"正在收到自动测试软件控制"的提示
         **/
        options.setExperimentalOption("excludeSwitches", Arrays.asList("enable-automation"));
        options.addArguments("--disable-blink-features");
        options.addArguments("--disable-blink-features=AutomationControlled");
//        options.addArguments("--headless");
        options.setExperimentalOption("useAutomationExtension", false);

        options.setExperimentalOption("prefs", prefs);
        // 创建驱动对象

        ChromeDriver driver = null;
        try {
            init();
            driver = new ChromeDriver(options);
        } catch (Exception e) {
            try {
                System.out.println("强制使用本地driver");
                initLocal();
                driver = new ChromeDriver(options);
            } catch (Exception exception) {
                exception.printStackTrace();
                return null;
            }
        }
        driver.manage().window().setSize(new Dimension(2000, 2000));
        if (StringUtils.isNotEmpty(preScript)) {
            // MapBuilder是依赖hutool工具包的api
            Map<String, Object> commandMap = MapBuilder.create(new LinkedHashMap<String, Object>()).put("source", preScript)
                    .build();
            // executeCdpCommand这个api在selenium3中是没有的,请使用selenium4才能使用此api
            ((ChromeDriver) driver).executeCdpCommand("Page.addScriptToEvaluateOnNewDocument", commandMap);

        }

        System.out.println("Driver创建完毕");
        return driver;
    }

    public static ChromeDriver getWebDriver() {
        // 去除seleium全部指纹特征
        Resource resource = resourceLoader.getResource("classpath:js/stealth.min.js");
        InputStream stream = null;
        try {
            stream = resource.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String js = IoUtil.readUtf8(stream);
        return getWebDriver(js);
    }

    public static void loadScript(ChromeDriver driver, InputStream stream, Object... args) {
        String js = IoUtil.readUtf8(stream);
        driver.executeScript(js, args);
    }

    public static void loadScript(ChromeDriver driver, String resourceUrl, Object... args) {
        Resource resource = resourceLoader.getResource(resourceUrl);
        InputStream stream = null;
        try {
            stream = resource.getInputStream();
            loadScript(driver, stream, args);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public static ChromeDriver getSingleWebDriver() {
        if (chromeDriver != null) {
            try {
                chromeDriver.get("http://www.baidu.com");
            } catch (Exception e) {
                System.out.println("浏览器挂了，重开");
                chromeDriver = getWebDriver();
            }
            return chromeDriver;
        }
        chromeDriver = getWebDriver();
        return chromeDriver;
    }
    public static void closeWebDriver(WebDriver driver) {
        driver.quit();
    }


}
